package com.accounting.client.frontend.product;

import java.util.ArrayList;
import java.util.List;

import com.accounting.client.ApplicationContext;
import com.accounting.client.frontend.product.handlers.CreatePurchaseRecordHandler;
import com.accounting.client.frontend.product.handlers.PurchaseRecordPackageHandler;
import com.accounting.client.frontend.product.search.PurchaseRecordSearchPanel;
import com.accounting.client.frontend.product.updates.UpdateRecordCountHandler;
import com.accounting.client.frontend.product.updates.UpdateRecordDateHandler;
import com.accounting.client.frontend.product.updates.UpdateRecordOperatorHandler;
import com.accounting.client.frontend.product.updates.UpdateRecordPriceHandler;
import com.accounting.client.remote.Services;
import com.accounting.client.remote.enumeration.StockLocation;
import com.accounting.client.remote.obj.PurchaseRecord;
import com.accounting.client.remote.transfer.SearchPurchaseRecordRequest;
import com.accounting.client.resource.BoxResources;
import com.accounting.client.session.ErrorHandler;
import com.accounting.client.session.SessionManager;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.Widget;

import corelib.client.NumberFormats;
import corelib.client.date.DateFormats;
import corelib.client.delegate.Action;
import corelib.client.delegate.DataCallback;
import corelib.client.resource.CommonResources;
import corelib.client.schedule.DeferredTask;
import corelib.client.search.PagingResult;
import corelib.client.ui.SimpleModal;
import corelib.client.ui.widget.SimpleDataModel;
import corelib.client.ui.widget.WidgetListener;
import corelib.client.ui.widget.dialog.SimpleDialog;
import corelib.client.ui.widget.dialog.SimpleLargeDialog;
import corelib.client.ui.widget.form.SimpleLabel;
import corelib.client.ui.widget.grid.SimpleDataGrid;
import corelib.client.ui.widget.grid.SimpleDataGridHandler;
import corelib.client.ui.widget.grid.cell.CellRenderer;
import corelib.client.ui.widget.grid.column.ColumnConfig;
import corelib.client.ui.widget.grid.column.ColumnConfigs;
import corelib.client.ui.widget.messagebox.SimpleMessageBox;
import corelib.client.ui.widget.page.PageBase;
import corelib.client.ui.widget.panel.SimpleLayoutPanel;
import corelib.client.ui.widget.toolbar.SimpleRibbon;
import corelib.client.ui.widget.toolbar.SimpleRibbonButton;
import corelib.client.ui.widget.toolbar.SimpleRibbonButton.ButtonSize;

public class PurchaseRecordManager extends PageBase<Widget> {
	
	private final static int MaxRecordsPerPage = 20;
	
	private int currentOffset = 0;
	private int currentRecordsPerPage = 0;
	
	private ProductStockTableHandler   purchaseStockHandler;
	private PurchaseRecordSearchPanel  searchPanel;
	private SimpleDataGrid<PurchaseRecord> purchaseStockTable;
	
	private SimpleRibbonButton updatePriceBtn;
	private SimpleRibbonButton updateDateBtn;
	private SimpleRibbonButton updateCountBtn;
	private SimpleRibbonButton updateOperatorBtn;
	
	private SimpleRibbonButton packageDetailBtn;
	private SimpleRibbonButton deleteBtn;
	
	private SimpleRibbon       toolBar;
	private SimpleRibbonButton previousBtn;
	private SimpleRibbonButton nextBtn;
	
	public PurchaseRecordManager() {
		setPageName("购买记录");
		setPageIcon(BoxResources.INSTANCE.inventory_24());
	}
	
	public int getCurrentOffset() {
		return this.currentOffset;
	}

	public void setCurrentOffset(int currentOffset) {
		this.currentOffset = currentOffset;
	}

	public SimpleDataGrid<PurchaseRecord> getPurchaseStockTable() {
		return this.purchaseStockTable;
	}

	@Override
	protected Widget createWidget() {
		toolBar = createToolBar();
		purchaseStockTable = new SimpleDataGrid<PurchaseRecord>(
			MaxRecordsPerPage, 
			purchaseStockHandler = new ProductStockTableHandler()
		);
		
		SimpleLayoutPanel layout = new SimpleLayoutPanel();
		layout.add(toolBar);
		layout.add(purchaseStockTable);
		layout.add(searchPanel = new PurchaseRecordSearchPanel(purchaseStockTable));
		layout.setWidgetTopHeight(toolBar, 0, Unit.PX, 80, Unit.PX);
		layout.setWidgetTopBottom(purchaseStockTable, 80, Unit.PX, 0, Unit.PX);
		return layout;
	}
	
	@Override
	protected void afterCreateWidget(Widget widgetCreated) {
		super.afterCreateWidget(widgetCreated);
		new DeferredTask().run(new ScheduledCommand(){
			@Override
			public void execute() {
				refresh();
			}
		},400);
	}

	protected SimpleRibbon createToolBar() {
		SimpleRibbon toolBar = new SimpleRibbon();
		toolBar.addPushButton(new SimpleRibbonButton("创建购买记录", 
		    BoxResources.INSTANCE.addStock32(), 
			ButtonSize.Medium, 
			new WidgetListener() {
				@Override
				public void valueUpdated(Widget widget) {
					SimpleLargeDialog.show(new CreatePurchaseRecordHandler(new Action(){
						@Override
						public void run() {
							refresh();
						}
					}));
				}
		}));
		toolBar.addSeparator(ButtonSize.Medium);
		toolBar.addPushButton(updateDateBtn = new SimpleRibbonButton("更新购买日期", 
			    BoxResources.INSTANCE.updateDate32(), 
			    ButtonSize.Medium, 
			    new WidgetListener(){
				@Override
				public void valueUpdated(Widget widget) {
					SimpleDialog.show(new UpdateRecordDateHandler(purchaseStockTable.getSelectedObject()));
				}
		}));
		toolBar.addPushButton(updatePriceBtn = new SimpleRibbonButton("更新购买价格", 
			    BoxResources.INSTANCE.updatePrice32(), 
			    ButtonSize.Medium, 
			    new WidgetListener(){
				@Override
				public void valueUpdated(Widget widget) {
					SimpleDialog.show(new UpdateRecordPriceHandler(purchaseStockTable.getSelectedObject()));
				}
		}));
		toolBar.addPushButton(updateCountBtn = new SimpleRibbonButton("更新购买数量", 
			    BoxResources.INSTANCE.updateCount32(), 
			    ButtonSize.Medium, 
			    new WidgetListener(){
				@Override
				public void valueUpdated(Widget widget) {
					SimpleDialog.show(new UpdateRecordCountHandler(purchaseStockTable.getSelectedObject()));
				}
		}));
		toolBar.addPushButton(updateOperatorBtn = new SimpleRibbonButton("更新操作员", 
			    BoxResources.INSTANCE.updateUser32(), 
			    ButtonSize.Medium, 
			    new WidgetListener(){
				@Override
				public void valueUpdated(Widget widget) {
					SimpleDialog.show(new UpdateRecordOperatorHandler(purchaseStockTable.getSelectedObject()));
				}
		}));
		toolBar.addSeparator(ButtonSize.Medium);
		toolBar.addPushButton(deleteBtn = new SimpleRibbonButton("删除", 
			BoxResources.INSTANCE.deleteOrder32(), 
			ButtonSize.Medium, 
			new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				final PurchaseRecord recordInfo = purchaseStockTable.getSelectedObject();
				SimpleMessageBox.confirm("删除", "您确定要删除 " +recordInfo.getProductName()+" 这条记录吗?", new DataCallback<Boolean>(){
					@Override
					public void onCompleted(Boolean data) {
						if (data == Boolean.TRUE){
							delete(recordInfo);
						}
					}
				});
			}
		}));
		toolBar.addSeparator(ButtonSize.Medium);
		toolBar.addPushButton(packageDetailBtn = new SimpleRibbonButton("查询库存物流", 
			BoxResources.INSTANCE.track32(), 
			ButtonSize.Medium, 
			new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				final PurchaseRecord stockInfo = purchaseStockTable.getSelectedObject();
				if (stockInfo != null 
				 && stockInfo.getLocation() == StockLocation.China.getLocation()) {
					SimpleLargeDialog.show(new PurchaseRecordPackageHandler(stockInfo));	
				}
			}
		}));
		toolBar.addSeparator(ButtonSize.Medium);
		toolBar.addPushButton(new SimpleRibbonButton("刷新", CommonResources.INSTANCE.refresh32(),
			ButtonSize.Medium, 
			new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				refresh();
			}
		}));
		toolBar.addPushButton(previousBtn = new SimpleRibbonButton("前页",
				CommonResources.INSTANCE.prev32(),
				ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						load(Math.max(currentOffset - MaxRecordsPerPage, 0));
					}
				}
		));
		toolBar.addPushButton(nextBtn = new SimpleRibbonButton("后页",
				CommonResources.INSTANCE.next32(),ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						load(Math.max(currentOffset + MaxRecordsPerPage, 0));
					}
				}
		));
		
		deleteBtn.setEnabled(false);
		updateDateBtn.setEnabled(false);
		updatePriceBtn.setEnabled(false);
		updateOperatorBtn.setEnabled(false);
		updateCountBtn.setEnabled(false);
		packageDetailBtn.setEnabled(false);
		nextBtn.setEnabled(false);
		previousBtn.setEnabled(false);
		packageDetailBtn.setEnabled(false);
		return toolBar;
	}
	
	public void delete(final PurchaseRecord info) {
		final String passport = SessionManager.getPassport();
		SimpleModal.show("努力删除中...");
		Services.ProductService.DeletePurchaseRecord(passport, info.getId(), new AsyncCallback<Boolean>(){
			@Override
			public void onFailure(Throwable caught) {
				SimpleModal.hide();
				ErrorHandler.handleServiceError(caught);
			}
			
			@Override
			public void onSuccess(Boolean result) {
				SimpleModal.hide();
				if (result == Boolean.TRUE) {
					Services.PackageService.RemovePackages(passport, info.getId(), new AsyncCallback<Boolean>(){
						@Override
						public void onFailure(Throwable caught) {
							ErrorHandler.handleServiceError(caught);
						}
						@Override
						public void onSuccess(Boolean result) {
							refresh();
						}
					});
				}
			}
		});
	}
	
	public void refresh() {
		searchPanel.reset();
		load(0);
	}
	
	private void load(int offset) {
		String passport = SessionManager.getPassport();
		SearchPurchaseRecordRequest request = searchPanel.getRequest();
		request.setOffset(offset);
		request.setLimit(MaxRecordsPerPage);
		
		SimpleModal.show("努力加载中...");
		Services.ProductService.SearchPurchaseRecords(passport, request,
			new AsyncCallback<PagingResult<PurchaseRecord>>(){
				@Override
				public void onFailure(Throwable caught) {
					SimpleModal.hide();
					ErrorHandler.handleServiceError(caught);
				}
				
				@Override
				public void onSuccess(PagingResult<PurchaseRecord> result) {
					SimpleModal.hide();
					currentOffset = result.getOffset();
					currentRecordsPerPage = result.getData().size();
					
					purchaseStockHandler.setObjects(result.getData());
					previousBtn.setEnabled(result.getOffset() > 0);
					nextBtn.setEnabled(currentRecordsPerPage > 0 && currentRecordsPerPage == MaxRecordsPerPage);
					deleteBtn.setEnabled(false);
					packageDetailBtn.setEnabled(false);
					updateDateBtn.setEnabled(false);
					updatePriceBtn.setEnabled(false);
					updateCountBtn.setEnabled(false);
					updateOperatorBtn.setEnabled(false);
				}
			}
		);
	}
	
	private class CountCellRenderer extends CellRenderer<PurchaseRecord> {
		@Override
		public void render(SimpleDataModel<PurchaseRecord> model,
						   ColumnConfig columnConfig, 
						   int rowIndex, 
						   int colIndex,
						   SafeHtmlBuilder sb){
			
			PurchaseRecord info = model.getObject();
			if (info.getCount() <= 0){
				sb.append(SimpleLabel.createDanger(info.getCount()+"").asSafeHtml());	
			}
			else {
				sb.append(SimpleLabel.createSuccess(info.getCount()+"").asSafeHtml());	
			}
		}
	}
	
	private class ProductStockTableHandler extends SimpleDataGridHandler<PurchaseRecord> {
		
		private final static String CName 		 = "CName";
		private final static String Operator 	 = "Buyer";
		private final static String Poster 	     = "Poster";
		private final static String Cost 		 = "Cost";
		private final static String Count 		 = "Count";
		private final static String Postage 	 = "Postage";
		private final static String Location	 = "Location";
		private final static String Rate	     = "Rate";
		private final static String DateCreated  = "DateCreated";
		private final static String Total	     = "Total";
		
		List<PurchaseRecord> data;
		
		@Override
		public List<ColumnConfig> createColumns() { 
			List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
			configs.add(ColumnConfigs.create(DateCreated, "购买时间",   30, HasAlignment.ALIGN_LEFT, DateFormats.YYYY_MM_DD));
			configs.add(ColumnConfigs.create(CName,  	  "产品名称",   70));
			configs.add(ColumnConfigs.create(Location,    "库存位置",      30));
			configs.add(ColumnConfigs.create(Count,  	  "购买数量(罐)",   30, new CountCellRenderer()));
			configs.add(ColumnConfigs.create(Postage,  	  "单件库存邮费",   50, NumberFormats.AUD));
			configs.add(ColumnConfigs.create(Cost,   	  "产品购买单价",    50, NumberFormats.AUD));
			configs.add(ColumnConfigs.create(Total,       "总价", 50, NumberFormats.AUD));
			configs.add(ColumnConfigs.create(Rate,        "实时汇率",    30));
			configs.add(ColumnConfigs.create(Operator,    "购买员",    50));
			configs.add(ColumnConfigs.create(Poster,      "邮寄员",    50));
			return configs;
		}
		
		@Override
		public void format(int index, SimpleDataModel<PurchaseRecord> model) {
			PurchaseRecord info = model.getObject();
			double total = info.getCount() * (info.getCost() + info.getPostage());
			
			model.set(DateCreated, info.getDateCreated());
			model.set(CName, 	   info.getProductName());
			model.set(Location,    StockLocation.getLocationByType(info.getLocation()).getCname());
			model.set(Operator,    ApplicationContext.getUser(info.getOperatorId()).getName());
			model.set(Poster, 	   ApplicationContext.getUser(info.getPostOperatorId()).getName());
			model.set(Cost, 	   info.getCost());
			model.set(Count, 	   info.getCount());
			model.set(Postage, 	   info.getPostage());
			model.set(Rate, 	   info.getRate());
			model.set(Total, 	   total);
		}
		
		public void setObjects(List<PurchaseRecord> objects) {
			this.data = objects;
			getGrid().setObjects(objects);
		}
		
		@Override
		public List<PurchaseRecord> getObjects() {
			return this.data;
		}
		
		@Override
		public void onObjectClicked(PurchaseRecord obj) {
			deleteBtn.setEnabled(true);
			updateDateBtn.setEnabled(true);
			updatePriceBtn.setEnabled(true);
			updateCountBtn.setEnabled(true);
			updateOperatorBtn.setEnabled(true);
			packageDetailBtn.setEnabled(obj.getLocation() == StockLocation.China.getLocation());
		}

		@Override
		public void onObjectDoubleClicked(PurchaseRecord obj) {
			onObjectClicked(obj);
		}
		
	}
	
}
